package com.example.esigntreasure.api.client;

import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.esigntreasure.api.bo.R;
import com.example.esigntreasure.api.config.ApiConfig;
import com.example.esigntreasure.api.dto.SignFlowDto;
import com.example.esigntreasure.api.dto.UploadFilesDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.imageio.stream.FileImageOutputStream;
import java.io.*;
import java.util.HashMap;
import java.util.Map;

/**
 * @author rgj
 * E签宝电子签章集成接口client
 * @create 2024-03-13 14:01
 */
@Slf4j
@Component
public class ApiClient {

    /**
     * 生成上传文件链接
     *
     * @param dto
     * @return
     */
    public R getUploadFilesUrl(UploadFilesDTO dto) {
        String accessResult = "";
        try {
            String signature = HMACSHA256(JSONObject.toJSONString(dto), ApiConfig.PROJECT_SECRET);
//            System.out.println("url==="+ApiConfig.HTTP_POST + ApiConfig.UPLOADFILE_URL);
//            System.out.println("signature==="+signature);
//            System.out.println("params==="+JSONObject.toJSONString(dto));
            accessResult = HttpUtil.createRequest(Method.POST, ApiConfig.HTTP_POST + ApiConfig.UPLOADFILE_URL)
                    .header("x-timevale-project-id", ApiConfig.PROJECT_ID)
                    .header("x-timevale-signature", signature)
                    .header("Content-Type", "application/json")
                    .body(JSONObject.toJSONString(dto))
                    .execute().body();
            log.info("【生成上传文件链接请求结果】【".concat(accessResult).concat("】"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return JSON.parseObject(accessResult, R.class);
    }

    /**
     * 上传文件
     *
     * @param url
     * @param file
     * @return
     */
    public R uploadFiles(String url, File file) {
//        String signature = HMACSHA256(data, ApiConfig.PROJECT_SECRET);
        Map<String, Object> params = new HashMap<>();
        params.put("file", file);
        String accessResult = HttpUtil.createRequest(Method.POST, url)
                .header("x-timevale-project-id", ApiConfig.PROJECT_ID)
                .header("x-timevale-signature", ApiConfig.PROJECT_SECRET)
                .header("Content-Type", "multipart/form-data")
                .form(params)
                .execute().body();
        log.info("【上传文件请求结果】【".concat(accessResult).concat("】"));
        return JSON.parseObject(accessResult, R.class);
    }

    /**
     * 下载文件
     *
     * @param fileKey
     * @return
     */
    public R downloadFile(String fileKey) {
        String accessResult = "";
        try {
            String signature = HMACSHA256("fileKey=" + fileKey, ApiConfig.PROJECT_SECRET);
            String url = ApiConfig.HTTP_POST + ApiConfig.DOWNLOADFILE_URL + "?fileKey="+fileKey;
            accessResult = HttpUtil.createRequest(Method.GET, url)
                    .header("x-timevale-project-id", ApiConfig.PROJECT_ID)
                    .header("x-timevale-signature", signature)
                    .header("Content-Type", "application/json")
                    .execute().body();
            log.info("【下载文件请求结果】【".concat(accessResult).concat("】"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return JSON.parseObject(accessResult, R.class);
    }

    /**
     * 下载文件流
     *
     * @param fileKey
     * @return
     */
    public void downloadFileStream(String fileKey) {
        int accessResult = 0;
        try {
            String signature = HMACSHA256("fileKey=" + fileKey, ApiConfig.PROJECT_SECRET);
            String url = ApiConfig.HTTP_POST + ApiConfig.FILE_STREAM_URL + "?fileKey="+fileKey;
            byte[] buffer = new byte[1024];
            accessResult = HttpUtil.createRequest(Method.GET, url)
                    .header("x-timevale-project-id", ApiConfig.PROJECT_ID)
                    .header("x-timevale-signature", signature)
                    .header("Content-Type", "application/octet-stream")
                    .getConnection().getInputStream().read(buffer);
//            log.info("【下载文件流请求结果】【".concat(accessResult).concat("】"));
//            BufferedInputStream bufferedInputStream = new BufferedInputStream(accessResult);
            //保存文件
            FileOutputStream fileOutputStream = new FileOutputStream("D:\\oafiles\\123.doc");
//            int bytesRead;
            while(accessResult!=-1){
                fileOutputStream.write(buffer,0,accessResult);
            }
            fileOutputStream.close();
//            bufferedInputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

//        return JSON.parseObject(accessResult, R.class);
    }

    /**
     * 一步发起签署流程
     *
     * @param dto
     * @return
     */
    public R createTask(SignFlowDto dto) {
        String accessResult = "";
        try {
            String signature = HMACSHA256(JSON.toJSONString(dto), ApiConfig.PROJECT_SECRET);
            accessResult = HttpUtil.createRequest(Method.POST, ApiConfig.HTTP_POST + ApiConfig.SIGNFLOW_URL)
                    .header("x-timevale-project-id", ApiConfig.PROJECT_ID)
                    .header("x-timevale-signature", signature)
                    .header("Content-Type", "application/json")
                    .body(JSON.toJSONString(dto))
                    .execute().body();
            log.info("【一步发起签署流程请求结果】【".concat(accessResult).concat("】"));
        } catch (Exception e) {
            e.printStackTrace();
        }

        return JSON.parseObject(accessResult, R.class);
    }

    public String HMACSHA256(String data, String key) throws Exception {
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256"));
        byte[] signData = mac.doFinal(data.getBytes("UTF-8"));
        StringBuilder sb = new StringBuilder();
        for (byte item : signData) {
            sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
        }
        return sb.toString();
    }
}
